<template>
  <div class="ek-tree">
    <ekInput v-model="filterText" :placeholder="placeholder" v-if="searchOn" />
    <div  class="ek-tree-content">
    <el-tree
      ref="treeRef"
      :data="data"
      :props="defaultProps"
      :show-checkbox="showCheckbox"
      :check-strictly="checkStrictly"
      :lazy="lazy"
      :load="load"
      :node-key="nodeKey"
      :default-expanded-keys="defaultExpandedKeys"
      :default-checked-keys="defaultCheckedKeys"
      :default-expand-all="defaultExpandAll"
      :expand-on-click-node="expandOnClickNode"
      :filter-node-method="handleFilterNodeMethod"
      :accordion="accordion"
      :allow-drop="allowDrop"
      :allow-drag="allowDrag"
      @node-click="handleNodeClick"
      @check-change="handleCheckChange"
      @node-drag-start="handleDragStart"
      @node-drag-enter="handleDragEnter"
      @node-drag-leave="handleDragLeave"
      @node-drag-over="handleDragOver"
      @node-drag-end="handleDragEnd"
      @node-drop="handleDrop"
         
    >

    </el-tree>
    </div>
  </div>
</template>

<script setup>
import { watch, ref, defineEmits, defineExpose } from "vue";

import ekInput from "@/components/form/ekInput/index.vue";
const props = defineProps({
  // 数据
  data: {
    type: Array,
    default: [],
  },
  // 配置项
  defaultProps: {
    type: Object,
    default: () => ({}),
  },
  // 是否显示选择框
  showCheckbox: {
    type: Boolean,
    default: false,
  },
  // 任意节点可选
  checkStrictly: {
    type: Boolean,
    default: false,
  },
  // 是否开启懒加载
  lazy: {
    type: Boolean,
    default: false,
  },
  // 节点key
  nodeKey: {
    type: String,
    default: "id",
  },
  // 默认展开节点
  defaultExpandedKeys: {
    type: Array,
    default: [],
  },
  // 默认选中节点
  defaultCheckedKeys: {
    type: Array,
    default: [],
  },
  // 默认展开所有
  defaultExpandAll: {
    type: Boolean,
    default: false,
  },
  // 点击节点触发展开/收缩
  expandOnClickNode: {
    type: Boolean,
    default: true,
  },
  // 开启手风琴效果
  accordion: {
    type: Boolean,
    default: false,
  },
  // 是否开启拖拽节点功能
  draggable: {
    type: Boolean,
    default: false,
  },
  // 拖拽时判定目标节点能否成为拖动目标位置。 如果返回 false
  allowDrop: {
    type: Function,
    default: () => false,
  },
  // 判断节点能否被拖拽 如果返回 false ，节点不能被拖动
  allowDrag: {
    type: Function,
    default: () => false,
  },
  // 开启搜索
  searchOn: {
    type: Boolean,
    default: true,
  },
  placeholder: {
    type:String,
    default:'请输入过滤条件'
  },
  load: {
    type: Function,
    default: () => {},
  }
});
// emit
const emit = defineEmits([
  "node-click",
  "check-change",
  "node-drag-start",
  "node-drag-enter",
  "node-drag-leave",
  "node-drag-over",
  "node-drag-end",
  "node-drop",
]);

// 节点点击
function handleNodeClick(data) {
  emit("node-click", data);
}

// checkbox change
function handleCheckChange(data, checked, indeterminate) {
  emit("check-change", data, checked, indeterminate);
}

function handleDragStart(node, event) {
  emit("node-drag-start", node, event);
}
function handleDragEnter(draggingNode, dropNode, event) {
  emit("node-drag-enter", draggingNode, dropNode, event);
}
function handleDragLeave(draggingNode, dropNode, event) {
  emit("node-drag-leave", draggingNode, dropNode, event);
}
function handleDragOver(draggingNode, dropNode, event) {
  emit("node-drag-over", draggingNode, dropNode, event);
}
function handleDragEnd(draggingNode, dropNode, dropType, event) {
  emit("node-drag-end", draggingNode, dropNode, dropType, event);
}
function handleDrop(draggingNode, dropNode, dropType, event) {
  emit("node-drop", draggingNode, dropNode, dropType, event);
}


const filterText = ref("");
watch(filterText, (val) => {
  treeRef.value.filter(val);
});

// 数据过滤
function handleFilterNodeMethod(value, data) {
  if (!value) return true;
  return data.label.includes(value);
}

const treeRef = ref(null);

// 获取选中节点
const getCheckedNodes = () => {
  return treeRef.value.getCheckedNodes(false, false);
};

// 获取选中节点key
const getCheckedKeys = () => {
  return treeRef.value.getCheckedKeys(false);
};
// 设置目前选中的节点, nodeKeys 数组
const setCheckedKeys = (nodeKeys) => {
  treeRef.value.setCheckedKeys(nodeKeys, false);
};
// 清除选中节点
const resetChecked = () => {
  treeRef.value.setCheckedKeys([], false);
};
// 
const getNode = (nodeKey) => {
  return treeRef.value.getNode(nodeKey);
};

// 更新节点孩子
const updateKeyChildren = (nodeKey, children) => {
   treeRef.value.updateKeyChildren(nodeKey, children);
};
// 
const setCheckedNodes = (nodeKeys) => {
   treeRef.value.setCheckedNodes(nodeKeys);
};

const setChecked = (node, checked, deep) => {
   treeRef.value.setChecked(node, checked, deep);
};
// 返回当前被选中节点的数据 (如果没有则返回 null)
const getCurrentKey = () => {
  return treeRef.value.getCurrentKey();
};
// 返回当前被选中节点的数据 (如果没有则返回 null)
const getCurrentNode = () => {
  return treeRef.value.getCurrentNode();
};
// 
const setCurrentKey = (key, shouldAutoExpandParent=true) => {
   treeRef.value.setCurrentKey(key, shouldAutoExpandParent);
};
const setCurrentNode = (key, shouldAutoExpandParent=true) => {
   treeRef.value.setCurrentNode(key, shouldAutoExpandParent);
};
// 删除 Tree 中的一个节点，使用此方法必须设置 node-key 属性
const remove = (data) => {
   treeRef.value.remove(data);
};
// 为 Tree 中的一个节点追加一个子节点
const append = (data) => {
   treeRef.value.append(data);
};
// 在 Tree 中给定节点前插入一个节点
const insertBefore = (newNode, existingNode) => {
   treeRef.value.insertBefore(newNode, existingNode);
};
// 在 Tree 中给定节点后插入一个节点
const insertAfter = (newNode, existingNode) => {
   treeRef.value.insertAfter(newNode, existingNode);
};

// todo 如何知道数据是否为叶子节点

// 暴露给外部的方法
defineExpose({
  getCheckedNodes,
  getCheckedKeys,
  setCheckedKeys,
  resetChecked,
  getNode,
  updateKeyChildren,
  setCheckedNodes,
  setCheckedNodes,
  setChecked,
  getCurrentKey,
  getCurrentNode,
  setCurrentKey,
  setCurrentNode,
  remove,
  append,
  insertBefore,
  insertAfter
});
</script>

<style scoped lang="scss">
.ek-tree {
  height: 100%;
  >.ek-tree-content {
      margin-top: 8px;
      height: calc(100% - 34px);
      overflow: auto;
  }

}

::v-deep .el-tree-node {
  &.is-current {
    >.el-tree-node__content {
      background-color: #f5f7fa;
   }
  }
}
</style>
